<?php
	defined('_JEXEC') or die('Restricted access');
   
	//
	// t_base_field
	//
	class t_field_event
	{
		public function __construct($a_event_type,$a_event_name,$a_action_name,$a_body_code)
		{
			$this->event_type = $a_event_type;
			$this->event_name = $a_event_name;
			$this->hashed_action_name = md5($a_action_name);
			$this->body_code = $a_body_code;
		}
	}
		
	//
	// t_base_field
	//
	abstract class t_base_field implements i_base_field 
	//abstract class t_base_field
	{


        // property declaration
		// private
        // C
		public $custom_file_exist = false;
			 
		// property declaration
		// public
		// B
		public $base_field_type = null;
		// C
        const common_properties_position_per_field_type = 1;
        const common_properties_position_per_field_name = 2;
        const common_properties_position_per_field_parent_index = 3; //Values: -1 = current last position; -2 = first position; -3 = always last position ; > 0 specified position
        const common_properties_position_last = 4;
		
		// E
		public $events = array();
		// F
		const field_event_type_on_selected = 1;       
        const field_event_type_on_edit = 2; 
        const field_event_type_on_cancel = 3; 
        const field_event_type_on_save = 4; 
		const field_event_type_on_insert = 5;
        const field_event_type_on_reload = 6;
        const field_event_type_on_delete = 7;
        const field_event_type_on_paging = 8;
        const field_event_type_last = 9; 
		// E
		const error_msg_class_name = "t_field_error_msg";
        // L
        public $lang = array();	
        // N
        public $name = '';
        // P
        public $parent_component = null;
        public $parent_part = null;
        
        // T
        public $tags = array();
        // U
        public $uses_as_included_in = false;

		// property declaration
		// protected
		// A
		protected $action_as_method_name = '';
        // C
        protected $common_properties_array = array();
        // D
        protected $default_start_tag = null;
        protected $default_result_tag = null;
		// M
        protected $main_tag = null;
		

        // P
        protected $proper_properties_array = array();
        // R
        protected $result_action_script = '';
		// S
		protected $source_action_script = '';
		protected $start_action_script = '';
         //V
        protected $value_db_fields = array();
       
        // method declaration
		// private    

        // method declaration
		// protected    
        // A
		protected function add_style_sheet_property($a_style_sheet_selector,$a_style_sheet_property_name,$a_style_sheet_property_value)
		{
			$this->parent_component->main_tag->header_script_generator->add_style_sheet_property($a_style_sheet_selector,$a_style_sheet_property_name,$a_style_sheet_property_value);
		}
		
        protected function add_tag($a_tag_type,$a_tag_name,$a_parent_tag = null)
		{
           // echo "add_tag - this->name: $this->name - a_tag_name:$a_tag_name<br>";
			if ($a_parent_tag === null)
            {
	/* *** TO VERIFY *** */			$local_parent_tag = $this->get_parent_tag();
				//echo "a_tag_name: $a_tag_name - local_parent_tag: $local_parent_tag->name<br>";	
            }
            else
            {
                $local_parent_tag = $a_parent_tag;
            }
			if ($this->uses_as_included_in)
			{
				$this->tags[$a_tag_name] = new t_base_tag($a_tag_type,$a_tag_name);
			}
			else
			{
				// CREATES A TAG BINDING WITH MAIN FIELD
				//echo "CREATES A TAG BINDING WITH MAIN FIELD<br>";
			    $this->tags[$a_tag_name] = $local_parent_tag->create_and_add_child_at_bottom($a_tag_type,$a_tag_name);
            }
			return $this->tags[$a_tag_name];
        }
		// G
		protected function get_call_back_actions_names()
		{
			return '[]';
		}	

		protected function get_javascript_events_list_initialization()
		{
			
		}
		//gets html code to fire event type action on html element
        abstract protected function get_proper_properties_position_last();
		abstract protected function get_field_event_script($a_event_type,$a_argouments);

        

        // method declaration
		// public        
		public function __construct($a_parent_part,$a_common_properties_str, $a_proper_properties_str) 
		{
			global $g_ambient_namespace;
			global $g_strings_utility_namespace;
			//echo "a_field_str: $a_field_str<br>";
			$this->parent_part =$a_parent_part;
            $this->parent_component = $this->parent_part->parent_component;
            /* LANGUAGES  */
			$g_ambient_namespace->load_language($this);
			
            //
			$this->common_properties_array = explode(t_query_parameter::separator_level_1,
                $a_common_properties_str);
            //echo "a_common_properties_str(".count($this->common_properties_array)."): $a_common_properties_str <BR>";    
            if ((count($this->common_properties_array)-1) != self::common_properties_position_last)  
			{
                throw new Exception('Error creating class '.get_class($this).
					'. Not enough common properties were specified('.
                    (count($this->common_properties_array)-1) . ' instead of '.
                    self::common_properties_position_last.').');
			}
			
		    $this->name = $this->common_properties_array[self::common_properties_position_per_field_name];
            //echo "NAME: ".$this->common_properties_array[self::common_properties_position_per_field_name]."<br>";
            /* */   
			//echo "a_proper_properties_str: $a_proper_properties_str<br>";
            /*if (strpos($a_proper_properties_str, '__CE_DEPTH_1_') !== false)
			{
				echo $a_proper_properties_str."<br>";
				echo $g_strings_utility_namespace->get_disguised_value($a_proper_properties_str)."<br>";
			}*/
			$this->proper_properties_array = explode(t_query_parameter::separator_level_1,
                $g_strings_utility_namespace->get_disguised_separator($a_proper_properties_str));
			/*foreach ($this->proper_properties_array as $local_index => $local_value) 
				$this->proper_properties_array[$local_index] = $g_strings_utility_namespace->get_disguised_value($local_value);*/
			/* the first element and the last are not significant */	
			$local_count = count($this->proper_properties_array)-2;
			//echo "class: ".get_class($this)." - local_count: $local_count - last: ".$this->get_proper_properties_position_last()."<br>";
			//print_r($this->proper_properties_array);
            if ($local_count >= ($this->get_proper_properties_position_last()))
			{
				
				
				throw new Exception('Error creating class '.get_class($this).
                    '. Too many proper properties were specified('.
                    $local_count . ' instead of '.
                    ($this->get_proper_properties_position_last()-1).').');
			}
			else
			{
					
				// add default values
				   for($local_index = $local_count+1; $local_index < ($this->get_proper_properties_position_last()); $local_index++)
				   {
						//echo "this->name: $this->name - local_index: $local_index<br>";
						$this->proper_properties_array[$local_index] = $this::get_default_proper_property($local_index);
						//echo "this->proper_properties_array[$local_index]: ". $this->proper_properties_array[$local_index]."<br>"; 
				   }
				   
			}
    
           // $this->initialize_common_field();
           
		}
		public function __call($name, $arguments) 
		{
			// included file
            $local_return = array();
			$local_file_name = get_class($this) . "_$name";
			//echo "local_file_name: $local_file_name<br>";
			$local_field_path = CUTEENGINE_FIELDS_PATH . substr(get_class($this),2,strlen(get_class($this))) . DIRECTORY_SEPARATOR  ;
			//echo "local_field_path.local_file_name.php: $local_field_path$local_file_name.php <br>";
			//echo CUTEENGINE_PATH_CUSTOM_FILES . $local_file_name . "_" . $this->parent_component->id . ".php<br>";
			if (($this->custom_file_exist) || (file_exists(CUTEENGINE_PATH_CUSTOM_FILES . $local_file_name . "_" . $this->parent_component->id . ".php")))
			{	
				$this->custom_file_exist = true;
				require(CUTEENGINE_PATH_CUSTOM_FILES . $local_file_name . "_" . $this->parent_component->id . ".php");
			}	
			else /*if (file_exists("$local_field_path$local_file_name.php"))*/
				require("$local_field_path$local_file_name.php");
			/*else
            {
				//throw new Exception("Error calling method '$name' for object class '".get_class($this)."' id: ".$this->id."<br>");
                //$this->log->add_log_on_page("files '$local_file_name.php' and '$local_file_name" . "_" . $this->id . ".php' not found.");     
            }    */
			//echo "local_return: $local_return <br>";	
			return $local_return;
		}
		// A
		public function add_content_to_a_method_only_for_the_current_field_instance($a_method_name,$a_content)
		{
			global $g_javascript_namespace;
			$g_javascript_namespace->header_script_generator->add_content_to_a_method(get_class($this),
				$a_method_name,"
					if (this.name == '".$this->name."')
					{
						$a_content;
					}
					");
		}
		public function add_event($a_event_type,$a_event_name,$a_body_code)
		{
			//echo "a_event_name:$a_event_name<br>";
            //echo get_class($this)." - named: $this->name<br>";
			$local_action_name = $this->parent_part->get_call_back_action_name($a_event_type);
			$local_event = new t_field_event($a_event_type,$a_event_name,$local_action_name,$a_body_code); 
			
			if ($this->events[$a_event_type])
			{
				throw new Exception('Error creating object class '.get_class($this).
					" named: \"".$this->name."\". Event \"$a_event_name\" already exist.");	
			}
			else
			{
				$this->events[$a_event_type] = $local_event;
				$this->initialize_field_event($a_event_type);
			}
		}
        // C
        public static function create_field_from_string($a_parent_part,$a_field_str)
        {
            //echo "a_field_str: $a_field_str<br>";
            global $g_cuteengine;
            global $g_ambient_namespace;
			$local_field = null;
			//
			$local_field_properties = explode(t_query_parameter::separator_level_1,$a_field_str);
            $local_common_properties_str = implode(t_query_parameter::separator_level_1, array_slice($local_field_properties,0,self::common_properties_position_last)) . 
                t_query_parameter::separator_level_1; 
            $local_class_type = $local_field_properties[self::common_properties_position_per_field_type];  
            //echo "a_field_str:$a_field_str <BR>local_class_type:$local_class_type<BR>";
			$local_proper_properties_str = t_query_parameter::separator_level_1 . 
                implode(t_query_parameter::separator_level_1, array_slice($local_field_properties, self::common_properties_position_last));
			//	
			$local_name = $local_field_properties[self::common_properties_position_per_field_name]; 
			$local_file_name = substr($local_class_type,2,strlen($local_class_type));
            $local_path = CUTEENGINE_FIELDS_PATH. $local_file_name . DIRECTORY_SEPARATOR  ;
            //echo "$local_path$local_file_name.php <br>";   
            if (file_exists("$local_path$local_file_name.php"))
            {      
                if (!array_key_exists ($local_name, $g_cuteengine->fields_list))
				{
					require_once("$local_path$local_file_name.php"); 
					//echo "local_field_properties[self::common_properties_position_per_field_type]:" .$local_field_properties[self::common_properties_position_per_field_type]."<br>"; 
                    $g_ambient_namespace->autoload_content = 'fields_content';
					$local_field = new $local_class_type($a_parent_part,
						$local_common_properties_str,$local_proper_properties_str);	 
					$local_field->name = $local_name; 
					//echo "aggiungo field_name: $local_name al g_cuteengine->fields_list<br>";
					$g_cuteengine->fields_list[$local_name] =  $local_field;  	
				}
				else
				{
					 echo 'Error, field name '.$local_name.' already exist.';
					 //throw new Exception('Error, field name '.$local_name.' already exist.');
				}
            } 
			else
			{
				 throw new Exception('Error field class "'.$local_class_type.'". Class file not found.');
			}
			return $local_field;
        }
        // C 
		// this method permit to add method or function used to manage data in javascript script
		abstract public function create_javascript_initialization_component();   
        
   		public function create_tags_structure($a_arguments_names = '',$a_arguments_values = '')
        {
            $local_arguments_names = '';
            $local_arguments_values = '';
            if ($a_arguments_names != '')
            {
                $local_arguments_names = ','.$a_arguments_names;
                $local_arguments_values = ','.$a_arguments_values;
            }    
            global $g_javascript_namespace;
			global $g_strings_utility_namespace;
            $g_javascript_namespace->header_script_generator->add_class(
				t_base_field,'',t_base_display_component::base_javascript_component_name());        
            $g_javascript_namespace->header_script_generator->add_class(
				get_class($this),'a_cuteengine,a_name,a_parent_componet_name,a_log_componet_name,a_component_id,a_events_array'.$local_arguments_names,t_base_field);        
			$local_log_tag_name = $this->parent_component->get_log_tag_name();	
            $g_javascript_namespace->header_script_generator->add_cuteengine_component_as_property_of_a_class(
                get_class($this),$this->name,"t_cuteengine",$this->parent_component->name,$local_log_tag_name,'0',
					$this->get_call_back_actions_names().$local_arguments_values);      
            //properties
			$g_javascript_namespace->header_script_generator->add_property_to_a_class(
                get_class($this),'cuteengine','a_cuteengine',false);
            // C    
            $g_javascript_namespace->header_script_generator->add_cuteengine_component_as_property_of_a_class(
                t_content_loader,"content_loader",get_class($this),$this->name,'','0');  
            // E
			$g_javascript_namespace->header_script_generator->add_property_to_a_class(
                get_class($this),'events_list',"new Array()",false);
			$this->get_javascript_events_list_initialization();
			// N
			$g_javascript_namespace->header_script_generator->add_property_to_a_class(
                get_class($this),'name',"a_name",false);	
            // P
			$g_javascript_namespace->header_script_generator->add_property_to_a_class(
                get_class($this),'parent_componet_name',"a_parent_componet_name",false);	    
			$g_javascript_namespace->header_script_generator->add_property_to_a_class(
                get_class($this),'log_componet_name',"a_log_componet_name",false);            
			// Methods    
			// G
			$g_javascript_namespace->header_script_generator->add_method_to_a_class_with_content(
				get_class($this),'get_tag_name','a_format_str,a_tag_name,a_argouments_array',"
	var local_re = /%s/i;
	var local_format_str = a_format_str;
	for (var i = 0; i < a_argouments_array.length; i++) 
	{
		local_format_str = local_format_str.replace (local_re, a_argouments_array[i]);
	}
	if (a_tag_name.trim() != '')
		return a_tag_name + local_format_str;
	else	
		return this.name + local_format_str;
	");
			// P
			$g_javascript_namespace->header_script_generator->add_method_to_a_class_with_content(
				t_base_field,'prepare_childs_values_to_send','a_content_name,a_argoument',"
	if (a_argoument == null)
		var local_result = '';
	else
		var local_result = a_argoument;	
	var local_parent = ".t_cuteengine::javascript_instance_name.".html_tag(a_content_name);
	var e = 0;
	for (var i = 0; i < local_parent.childNodes.length; i++) 
	{
		var child = local_parent.childNodes[i];
		if ((child.nodeName == 'INPUT') || (child.nodeName == 'TEXTAREA'))
		{
			var local_ce = ".t_cuteengine::javascript_instance_name."[child.id];
            if ((local_ce != undefined) && (local_ce.check_value != undefined) &&  (!local_ce.check_value()))
                return false;
            ".$g_strings_utility_namespace->get_javascript_code_to_hide_separetor("e","local_result","(child.type === 'checkbox' ? (child.checked ? '1' : '0' ) : child.value )")."
			e++;
		}
	} 
	return local_result;
	");
	
            // STYLE
			$this->add_style_sheet_property("." . self::error_msg_class_name,"color","red");
			$this->add_style_sheet_property("." . self::error_msg_class_name,"font-weight","bold");
			$this->add_style_sheet_property("." . self::error_msg_class_name,"padding-bottom","2px");

        }

		//F
        public function finalize_creation_field()
        {
            
        }

		// G
        public function get_included_in_html_structure($a_name)
		{
		}
		public function get_lang_count()
        {
            return (count($this->lang));
        }
		abstract public function get_language_position_last();
        public function get_index_in_the_parent_fields_list()
        {	
            return $this->common_properties_array[self::common_properties_position_per_field_parent_index];
		}
        // gets result script for action based on event type
		abstract public function get_result_action_script($a_event_type,$parent_event_type,
			$a_parameter,$a_content_loader_result);
			
		public function get_executor_field()
		{
            $local_result = null;
			/* get the html tag object that will include all the fields for execution */
			if (isset($this->parent_part->executor_field))
			{
				
				/* get from the executor field */ 
				$local_result = $this->parent_part->executor_field;
				//echo "local_result->name: ". $local_result->name. "<br>";
				
			}
			return $local_result;
			
				
        }
		
		public function get_executor_tag()
		{
			/* get the html tag object that will include all the fields for execution */
			
			$local_field = $this->get_executor_field(); 
			if (isset($local_field))
			{
				/* get from the executor field */ 
				$local_return_tag = $local_field->main_tag;
				
			}
			else	
				if (isset($this->parent_part->tag_for_more_fields))
				{
					$local_return_tag = $this->parent_part->tag_for_more_fields;
					//echo "2 - local_return_tag: $local_return_tag->name<br>";
				}
				else
				{
					$local_return_tag = $this->parent_part->main_tag;
					//echo "3 - local_return_tag: $local_return_tag->name<br>";
				}
			return $local_return_tag;		
				
        }
		
        public function get_main_tag()
        {	
            if (isset($this->main_tag))
                return $this->main_tag;
            else
                return null;
		}  
		public function get_part_tag()
		{
          
			$local_parent_tag = $this->parent_part->main_tag;
			//echo "local_parent_tag: $local_parent_tag->name<br>";
			return $local_parent_tag;		
				
        }
		
		public function get_parent_tag()
		{
            /* get the html tag object that will include the fields for the current part */
			
			$local_field = $this->get_executor_field();
			//echo "local_field: $local_field->name<br>";			
			if (isset($local_field) && ($local_field != $this))
			{
				/* get from a executor field the tag used for hosting children fields */ 
				
				$local_parent_tag = $local_field->main_tag;
				//echo "local_field: $local_field->name - local_parent_tag: $local_parent_tag->name<br>";
				
			}
			else	
				if (isset($this->parent_part->tag_for_more_fields))
				{
					$local_parent_tag = $this->parent_part->tag_for_more_fields;
					//echo "2 - local_parent_tag: $local_parent_tag->name<br>";
				}
				else
				{
					$local_parent_tag = $this->parent_part->main_tag;
					//echo "3 - local_parent_tag: $local_parent_tag->name<br>";
				}
			return $local_parent_tag;		
				
        }
		static function get_proper_properties_help($a_index)
		{	
			$local_return = '';
			for ($i=0; $i < $this->get_proper_properties_position_last(); $i++)
			{
				if ($local_return == '')
					$local_return = $this::get_help_proper_property($i);
				else
					$local_return .= ", ".$this::get_help_proper_property($i);
				
			}
		}
		
		static function get_default_value_proper_properties($a_index)
		{	
			$local_return = '';
			for ($i=0; $i < $this->get_proper_properties_position_last(); $i++)
			{
				if ($local_return == '')
					$local_return = $this::get_default_proper_property($i);
				else
					$local_return .= ", ".$this::get_default_proper_property($i);
				
			}
		}
		
        public function get_result_tag()
        {	
            if (isset($this->default_result_tag))
                return $this->default_result_tag;
            else
                return null;
		} 
        public function get_start_tag()
        {	
            if (isset($this->default_start_tag))
                return $this->default_start_tag;
            else
                return null;
		} 
        public function get_tag_name($a_format_str,$a_argouments_array,$a_new_name = '')
        {	
            $local_replace_count = 1;
            $local_return = $a_format_str;
            $local_count = substr_count($a_format_str,"%s");
            $local_count_array = count($a_argouments_array);
            if ($local_count <>$local_count_array)
                throw new Exception('Error, impossible to get tag name for field '.$this->name);
                
            for($local_index = 0; $local_index < $local_count; $local_index++)
            {
                $local_return = preg_replace("/%s/" ,  $a_argouments_array[$local_index], $local_return,$local_replace_count);
                //echo "local_return - $local_index - $a_argouments_array[$local_index]: $local_return <br>";
            }
            if ($a_new_name == '')
				return $this->name . $local_return;
			else
				return $a_new_name . $local_return;			
		} 
		//I
		//gets javascript code for executing of event action 
        abstract public function initialize_field_event($a_event_type);
		  
        public function initialize_main_tag()
        {	
            
		} 
		
        public function initialize_source_field($a_action)
        {	
            $this->source_action_script = $this->get_source_action_script($a_action);
		}        

		public function initialize_start_field($a_action)
        {	
            $this->start_action_script = $this->get_start_action_script($a_action);
		}	
		public function is_event($a_event_type)
        {
            return (($a_event_type >= self::field_event_type_on_selected) &&
                ($a_event_type <= self::field_event_type_last));	
        
        }
		public function is_event_able($a_event_type)
        {
            return array_key_exists($a_event_type,$this->events);	
        
        }		
        // M
        public function manage_result_from_db_on_child_action($a_query_parameter,$a_current_row_no,$a_rows_count,$a_action)
        {	
			$local_return = '';
			foreach ($this->value_db_fields as $local_field) 
			{
				$local_return .= 'local_array["'.$local_field.'"] = "'.$a_query_parameter->sql_values[$local_field].'";';
			}
            return $local_return;

        }     
        public function manage_result_on_child_action($a_action)
        {	
			$local_return = $this->action_call_code;
			
            return $local_return;

        }         
        
        public function get_db_field_name($a_field)
        {	
			$local_return = '';
			if (isset($a_field))
			{
				if (trim($a_field->orgname) == '')
					$local_return = $a_field->name;
				else	
					$local_return = $a_field->orgname;
			}
			
			
            return $local_return;

        }
	}
	
	interface i_base_field {
		static function get_default_proper_property($a_index);
		static function get_help_proper_property($a_index);
	}  
?>